package com.ellfors.module_first.index_rcv.widget

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.Typeface
import android.view.LayoutInflater
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.ellfors.common.ext.dp2px
import com.ellfors.common.ext.logD
import com.ellfors.common.ext.sp2px

/**
 * 分类、悬停的Decoration
 */
class SuspensionDecoration(context: Context) : RecyclerView.ItemDecoration() {

    private var mData: List<IndexTag>? = null

    private val mPaint = Paint()
    private val mBounds = Rect() //用于存放测量文字Rect

    private val mInflater: LayoutInflater

    private var mTitleHeight = 24.dp2px() //title的高
    private var headerViewCount = 0

    private var mTitleFontSize = 16.sp2px() //title字体大小
    private var mTitleBgColor = Color.parseColor("#FFFFFF")
    private var mTitleFontColor = Color.parseColor("#292A33")

    private var mTitlePaddingLeft = -1

    init {
        mPaint.textSize = mTitleFontSize.toFloat()
        mPaint.isAntiAlias = true
        mInflater = LayoutInflater.from(context)
    }

    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDraw(c, parent, state)
        val left = parent.paddingLeft
        val right = parent.width - parent.paddingRight
        val childCount = parent.childCount
        for (i in 0 until childCount) {
            val child = parent.getChildAt(i)
            val params = child.layoutParams as RecyclerView.LayoutParams
            var position = params.viewLayoutPosition
            position -= headerViewCount

            if (mData.isNullOrEmpty() || position > (mData?.size ?: 0) - 1 || position < 0 || mData?.get(
                    position
                )?.isShowSuspension == false) {
                continue
            }
            if (position == 0) {
                //等于0肯定要有title的
                drawTitleArea(c, left, right, child, params, position)
            } else {
                //其他的通过判断
                if (mData?.get(position)?.suspensionTag != mData?.get(position - 1)?.suspensionTag) {
                    //不为空 且跟前一个tag不一样了，说明是新的分类，也要title
                    drawTitleArea(c, left, right, child, params, position)
                }
            }
        }
    }

    /**
     * 绘制Title区域背景和文字的方法
     */
    private fun drawTitleArea(
        c: Canvas,
        left: Int,
        right: Int,
        child: View,
        params: RecyclerView.LayoutParams,
        position: Int
    ) {
        val data = mData?.get(position)
        data ?: return
        val paddingLeft = if (mTitlePaddingLeft == -1) {
            child.paddingLeft
        } else {
            mTitlePaddingLeft
        }

        //最先调用，绘制在最下层
        mPaint.color = mTitleBgColor
        c.drawRect(
            left.toFloat(),
            (child.top - params.topMargin - mTitleHeight).toFloat(),
            right.toFloat(),
            (child.top - params.topMargin).toFloat(),
            mPaint
        )
        mPaint.color = mTitleFontColor
        mPaint.getTextBounds(
            data.suspensionTag, 0, data.suspensionTag.length, mBounds
        )
        c.drawText(
            data.suspensionTag,
            paddingLeft.toFloat(),
            child.top - params.topMargin - (mTitleHeight.toFloat() / 2 - mBounds.height()
                .toFloat() / 2),
            mPaint
        )
    }

    override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        //最后调用
        // 绘制在最上层
        var pos =
            (parent.layoutManager as LinearLayoutManager?)?.findFirstVisibleItemPosition() ?: 0
        pos -= headerViewCount
        //pos为1，size为1，1>0? true
        if (mData.isNullOrEmpty() || pos > (mData?.size ?: 0) - 1 || pos < 0 || mData?.get(pos)?.isShowSuspension == false) {
            return
        }

        val tag = mData?.get(pos)?.suspensionTag
        val child = parent.findViewHolderForLayoutPosition(pos + headerViewCount)?.itemView
        //定义一个flag，Canvas是否位移过的标志
        var flag = false
        //防止数组越界（一般情况不会出现）
        if ((pos + 1) < (mData?.size ?: 0)) {
            if (tag != mData?.get(pos + 1)?.suspensionTag) {
                //当前第一个可见的Item的tag，不等于其后一个item的tag，说明悬浮的View要切换了
                // 开始变负，它的绝对值，是第一个可见的Item移出屏幕的距离，
                child?.also {
                    if (child.height + child.top < mTitleHeight) {
                        //当第一个可见的item
                        // 在屏幕中还剩的高度小于title区域的高度时，我们也该开始做悬浮Title的“交换动画”
                        //每次绘制前 保存当前Canvas状态，
                        c.save()
                        flag = true
                        //类似饿了么点餐时,商品列表的悬停头部切换“动画效果”
                        //上滑时，将canvas上移 （y为负数） ,所以后面canvas 画出来的Rect和Text都上移了，有种切换的“动画”感觉
                        c.translate(0f, (child.height + child.top - mTitleHeight).toFloat())
                    }
                }
            }
        }

        mPaint.color = mTitleBgColor
        c.drawRect(
            parent.paddingLeft.toFloat(),
            parent.paddingTop.toFloat(),
            (parent.right - parent.paddingRight).toFloat(),
            (parent.paddingTop + mTitleHeight).toFloat(),
            mPaint
        )
        mPaint.color = mTitleFontColor
        mPaint.getTextBounds(tag, 0, tag?.length ?: 0, mBounds)
        if (mTitlePaddingLeft != -1) {
            c.drawText(
                mData?.get(pos)?.suspensionTag ?: "",
                mTitlePaddingLeft.toFloat(),
                (parent.paddingTop + mTitleHeight - (mTitleHeight / 2 - mBounds.height() / 2)).toFloat(),
                mPaint
            )
        } else {
            c.drawText(
                tag ?: "",
                child?.paddingLeft?.toFloat() ?: 0F,
                (parent.paddingTop + mTitleHeight - (mTitleHeight / 2 - mBounds.height() / 2)).toFloat(),
                mPaint
            )
        }

        if (flag) {
            //恢复画布到之前保存的状态
            c.restore()
        }
    }

    override fun getItemOffsets(
        outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State
    ) {
        //super里会先设置0 0 0 0
        super.getItemOffsets(outRect, view, parent, state)
        var position = (view.layoutParams as RecyclerView.LayoutParams).viewLayoutPosition
        position -= headerViewCount
        if (mData.isNullOrEmpty() || position > (mData?.size ?: 0) - 1) {
            return
        }

        //我记得Rv的item position在重置时可能为-1.保险点判断一下吧
        if (position > -1) {
            val currentData = mData?.get(position)
            if (currentData?.isShowSuspension == true) {
                if (position == 0) {
                    outRect.set(0, mTitleHeight, 0, 0)
                } else if (currentData.suspensionTag != mData?.get(position - 1)?.suspensionTag) {
                    //不为空 且跟前一个tag不一样了，说明是新的分类，也要title
                    outRect.set(0, mTitleHeight, 0, 0)
                }
            }
        }
    }

    fun setTitleHeight(mTitleHeight: Int): SuspensionDecoration {
        this.mTitleHeight = mTitleHeight
        return this
    }

    fun setTitleBgColor(colorTitleBg: Int): SuspensionDecoration {
        mTitleBgColor = colorTitleBg
        return this
    }

    fun setTitleFontColor(colorTitleFont: Int): SuspensionDecoration {
        mTitleFontColor = colorTitleFont
        return this
    }

    fun setTitleFontSize(titleFontSize: Int): SuspensionDecoration {
        mTitleFontSize = titleFontSize
        mPaint.textSize = titleFontSize.toFloat()
        return this
    }

    fun setTitleFontBold(): SuspensionDecoration {
        mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD))
        return this
    }

    fun setData(data: List<IndexTag>?): SuspensionDecoration {
        this.mData = data
        return this
    }

    fun setHeaderViewCount(headerViewCount: Int): SuspensionDecoration {
        this.headerViewCount = headerViewCount
        return this
    }

    fun setTitlePaddingLeft(padding: Int): SuspensionDecoration {
        this.mTitlePaddingLeft = padding
        return this
    }
}
